package com.ayu.shortlink.admin.job;

import cn.hutool.core.collection.CollUtil;
import com.ayu.shortlink.admin.common.enums.CouponTaskStatusEnum;
import com.ayu.shortlink.admin.dao.entity.CouponTaskDO;
import com.ayu.shortlink.admin.dao.mapper.CouponTaskMapper;
import com.ayu.shortlink.admin.mq.basics.event.CouponTaskDelayExecuteEvent;
import com.ayu.shortlink.admin.mq.producer.CouponTaskDelayExecuteProducer;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;

/**
 * Xxl-Job处理任务
 */
@Component
@RequiredArgsConstructor
public class CouponTaskJobHandler extends IJobHandler {
    private final CouponTaskMapper couponTaskMapper;
    private final CouponTaskDelayExecuteProducer couponTaskDelayExecuteProducer;
    private final Integer MAX_LIMIT = 100;

    @Override
    @XxlJob(value = "couponTaskJobHandler")
    public void execute() throws Exception {
        long init = 0L;
        Date now = new Date();
        while (true){
            List<CouponTaskDO> unDoTaskList = fetchCouponTaskList(init,now);

            if(CollUtil.isEmpty(unDoTaskList)){
                break;
            }

            unDoTaskList.forEach(this::handler);
            //证明数据库中暂时没有数据了 直接停止
            if(unDoTaskList.size() < MAX_LIMIT){
                break;
            }
            //然后需要更新init
            init = unDoTaskList
                    .stream()
                    .mapToLong(CouponTaskDO::getId)
                    .max()
                    .orElse(init);
        }
    }

    /**
     * 查询数据库符合发布的任务
     */
    private List<CouponTaskDO> fetchCouponTaskList(long init, Date now){
        LambdaQueryWrapper<CouponTaskDO> queryWrapper = Wrappers.lambdaQuery(CouponTaskDO.class)
                .eq(CouponTaskDO::getStatus, CouponTaskStatusEnum.PENDING.getStatus())
                .le(CouponTaskDO::getSendTime, now)
                .gt(CouponTaskDO::getId, init)
                .last("LIMIT " + MAX_LIMIT);
        return couponTaskMapper.selectList(queryWrapper);
    }

    /**
     * 进行处理：1、将任务设置为执行中的事件 2、发送MQ进行消费
     */
    private void handler(CouponTaskDO couponTaskDO){
        CouponTaskDelayExecuteEvent event = CouponTaskDelayExecuteEvent.builder()
                .couponTaskId(couponTaskDO.getId())
                .status(CouponTaskStatusEnum.IN_PROGRESS.getStatus())
                .build();
        //发送MQ
        couponTaskDelayExecuteProducer.sendMessage(event);
    }
}
